package com.cyw.search.service.impl;

import cn.easyes.core.biz.PageInfo;
import cn.easyes.core.conditions.LambdaEsQueryWrapper;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cyw.common.core.domain.R;
import com.cyw.common.core.domain.entity.SysUser;
import com.cyw.common.helper.LoginHelper;
import com.cyw.common.utils.SetUtils;
import com.cyw.product.KafkaProducer;
import com.cyw.search.entity.user.EsUser;
import com.cyw.search.mapper.EsUserMapper;
import com.cyw.search.service.SearchEsUserService;
import com.cyw.search.utils.GetAddressByGeoPointUtil;
import com.cyw.system.mapper.SysUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author: Chenyw
 * @Date: 2022/11/04/16:53
 */
@Slf4j
@Service
public class SearchEsUserServiceImpl implements SearchEsUserService {
    @Resource
    private EsUserMapper esUserMapper;

    @Resource
    private KafkaProducer kafkaProducer;

    @Resource
    private SysUserMapper sysUserMapper;

    @Override
    public PageInfo<EsUser> searchNearUsers(String geoPoint, Integer pageNum, Integer pageSize) {
        LambdaEsQueryWrapper<EsUser> wrapper = new LambdaEsQueryWrapper<>();
        GeoPoint centerPoint = new GeoPoint(geoPoint);
        wrapper.geoDistance(EsUser::getLocation, 10.0, DistanceUnit.KILOMETERS, centerPoint)
            .orderByDistanceAsc(EsUser::getLocation, centerPoint);
        return esUserMapper.pageQuery(wrapper,pageNum,pageSize);
    }
    
    @Override
    public void saveOrUpdateUser(Long userId) {
        EsUser esUser = new EsUser();
        esUser.setUserId(userId);
        String localDateTimeNowStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        esUser.setCreateTime(localDateTimeNowStr);
        esUserMapper.insert(esUser);
        log.info("{}","用户存入es成功!!!");
    }

    @Override
    public R followOrUnFollow(Long userId)  {

        EsUser esUser = esUserMapper.selectById(userId);
        EsUser me = esUserMapper.selectById(LoginHelper.getUserId());

        Set<Long> loveMeSet = esUser.getLoveMeSet();
        Set<Long> iLoveSet = me.getILoveSet();

        if (!loveMeSet.contains(LoginHelper.getUserId())){
            loveMeSet.add(LoginHelper.getUserId());
            iLoveSet.add(userId);
            saveOrUpdateLove(esUser,me,loveMeSet,iLoveSet);

            // 给user_topic发送消息
            Map<String, Object> map = new HashMap<>(3);
            map.put("loginUserId",LoginHelper.getUserId()+"");
            map.put("userId",userId+"");
            map.put("type","1");
            String msg = JSON.toJSONString(map);
            kafkaProducer.sendMessageToUser(msg);
            return R.ok("关注成功!!");
        }else {
            loveMeSet.remove(LoginHelper.getUserId());
            iLoveSet.remove(userId);
            saveOrUpdateLove(esUser,me,loveMeSet,iLoveSet);
            return R.ok("取关成功!!");
        }
    }

    @Override
    public R updateGeoPoint(String geoPoint) {
        EsUser esUser = esUserMapper.selectById(LoginHelper.getUserId());
        GeoPoint centerPoint = new GeoPoint(geoPoint);
        esUser.setLocation(centerPoint.getLat()+","+centerPoint.getLon());
        esUser.setAddress(GetAddressByGeoPointUtil.getAddress(centerPoint));
        esUser.setLocation(geoPoint);
        String localDateTimeNowStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        esUser.setUpdateTime(localDateTimeNowStr);
        esUserMapper.insert(esUser);
        return R.ok();
    }

    @Override
    public List<SysUser> getHotUser() {
        EsUser esUser = esUserMapper.selectById(LoginHelper.getUserId());
        LambdaEsQueryWrapper<EsUser> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.notIn(EsUser::getUserId,esUser.getILoveSet()).orderByDesc(EsUser::getScore).limit(5);
        return getUser(wrapper);
    }

    @Override
    public List<SysUser> getRankUser() {
        LambdaEsQueryWrapper<EsUser> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.orderByDesc(EsUser::getScore).limit(10);
        return getUser(wrapper);
    }

    private List<SysUser> getUser(LambdaEsQueryWrapper<EsUser> wrapper) {
        List<EsUser> esUsers = esUserMapper.selectList(wrapper);
        List<Long> ids = esUsers.stream().map(EsUser::getUserId).collect(Collectors.toList());
        List<SysUser> sysUsers = sysUserMapper.selectBatchIds(ids);
        sysUsers.forEach(u -> u.setNickName(u.getNickName().substring(0, 1)));
        return sysUsers;
    }

    @Override
    public EsUser aboutMe() {
        SysUser sysUser = sysUserMapper.selectUserById(LoginHelper.getUserId());
        EsUser esUser = esUserMapper.selectById(LoginHelper.getUserId());
        esUser.setSysUser(sysUser);
        return esUser;
    }

    @Override
    public R loveCount() {
        EsUser esUser = esUserMapper.selectById(LoginHelper.getUserId());
        HashMap<String, Integer> map = new HashMap<>(2);
        map.put("iLikeCount",esUser.getILoveSet().size());
        map.put("likeMeCount",esUser.getLoveMeSet().size());
        return R.ok(map);
    }

    @Override
    public Page<SysUser> loveMeUser(Integer pageNum,Integer pageSize) {
        EsUser esUser = esUserMapper.selectById(LoginHelper.getUserId());
        Set<Long> loveMeSetIds = esUser.getLoveMeSet();
        LambdaQueryWrapper<SysUser> wrapper = sysUserWrapper(loveMeSetIds);
        return sysUserMapper.selectPage(new Page<>(pageNum,pageSize), wrapper);
    }

    @Override
    public Page<SysUser> iLoveUser(Integer pageSize, Integer pageNum) {
        EsUser esUser = esUserMapper.selectById(LoginHelper.getUserId());
        Set<Long> iLoveSetIds = esUser.getILoveSet();
        LambdaQueryWrapper<SysUser> wrapper = sysUserWrapper(iLoveSetIds);
        return sysUserMapper.selectPage(new Page<>(pageNum,pageSize), wrapper);
    }

    @Override
    public Page<SysUser> myFriends(Integer pageSize, Integer pageNum) {
        EsUser esUser = esUserMapper.selectById(LoginHelper.getUserId());
        Set<Long> containList = SetUtils.getContainSet(esUser.getLoveMeSet(), esUser.getILoveSet());
        LambdaQueryWrapper<SysUser> wrapper = sysUserWrapper(containList);
        return sysUserMapper.selectPage(new Page<>(pageNum,pageSize), wrapper);
    }

    private LambdaQueryWrapper<SysUser> sysUserWrapper(Set<Long> ids){
        LambdaQueryWrapper<SysUser> wrapper = Wrappers.lambdaQuery();
        wrapper.in(SysUser::getUserId,ids)
                .select(SysUser::getAge)
                .select(SysUser::getAvatar)
                .select(SysUser::getMarry)
                .select(SysUser::getEducation)
                .select(SysUser::getSex)
                .select(SysUser::getNickName)
                .select(SysUser::getUserId);
        return wrapper;
    }

    /**
     * 关注(取关)-逻辑
     */
    private void saveOrUpdateLove(EsUser esUser,EsUser me,Set<Long> loveMeSet ,Set<Long> iLoveSet){
        esUser.setLoveMeSet(loveMeSet);
        me.setILoveSet(iLoveSet);

        esUserMapper.insert(esUser);
        esUserMapper.insert(me);
        }


}
